package com.tanhua.server.service;

import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.tanhua.commons.templates.AipFaceTemplate;
import com.tanhua.commons.templates.HuanXinTemplate;
import com.tanhua.commons.templates.OssTemplate;
import com.tanhua.commons.templates.SmsTemplate;
import com.tanhua.domain.db.Question;
import com.tanhua.domain.db.Settings;
import com.tanhua.domain.db.User;
import com.tanhua.domain.db.UserInfo;
import com.tanhua.domain.mongo.UserLike;
import com.tanhua.domain.vo.*;
import com.tanhua.dubbo.api.*;
import com.tanhua.dubbo.api.mongo.FriendApi;
import com.tanhua.dubbo.api.mongo.UserLikeApi;
import com.tanhua.server.interceptor.UserHolder;
import com.tanhua.server.utils.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.Reference;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.http.ResponseEntity;
import org.springframework.messaging.MessagingException;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.*;

/**
 * @Service 加入springioc容器，给controller注入使用
 * 导入的包：org.springframework.stereotype.Service
 */
@Service
@Slf4j
public class UserService{
    // @Reference 注入dubbo服务接口的代理对象
    // 导入dubbo的包：org.apache.dubbo.config.annotation.Reference
    // 作用：对接口生成代理，通过代理远程调用
    @Reference
    private UserApi userApi;
    @Reference
    private UserInfoApi userInfoApi;
    @Reference
    private SettingsApi settingsApi;
    @Reference
    private QuestionApi questionApi;
    @Reference
    private BlackListApi blackListApi;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;
    @Autowired
    private SmsTemplate smsTemplate;
    @Autowired
    private HuanXinTemplate huanXinTemplate;
    @Autowired
    private RocketMQTemplate rocketMQTemplate;

    // 定义redis中存储的验证码的key的前缀
    private final String SMS_KEY = "SMS_KEY_";
    private final String TOKEN_KEY = "TOKEN_KEY_";
    // 获取配置文件中的tanhua.secret中的密钥值
    @Value("${tanhua.secret}")
    private String secret;

    /**
     * 接口名称：登录第一步---手机号登录
     * 需求描述：发送验证码
     */
    public ResponseEntity<Object> login(String phone) {
        //1. 生成验证码
        String code = (int)((Math.random()*9+1)*100000) + "";
        code = "123456";
        //2. 把验证码存储到redis
        redisTemplate.opsForValue().set(SMS_KEY+phone,code, Duration.ofMinutes(5));
        //3. 发送验证码
        //smsTemplate.sendSms(phone,code);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：登录第二步---验证码校验
     */
    public ResponseEntity<Object> loginVerification(
            String phone, String verificationCode) {
        //1. 从redis中获取验证码
        String key = SMS_KEY + phone;
        String redisCode = redisTemplate.opsForValue().get(key);

        //2. 验证码校验
        if (StringUtils.isEmpty(redisCode) || !redisCode.equals(verificationCode)) {
            // 验证码校验失败
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        //3. 验证码校验成功，删除验证码
        redisTemplate.delete(key);

        //4. 根据手机号码查询
        User user = userApi.findByMobile(phone);
        //5. 判断：如果没有查询到数据，就自动注册
        boolean isNew = false;
        // 操作类型： 0101 登陆
        String type = "0101";
        if (user == null) {
            user = new User();
            user.setMobile(phone);
            user.setPassword(DigestUtils.md5Hex("123456"));
            // 保存用户
            Long userId = userApi.save(user);
            // 设置标志为新注册用户
            isNew = true;

            // 设置用户id（生成token时候可以统一获取用户id）
            user.setId(userId);

            // 【自动完成环信注册】
            huanXinTemplate.register(userId);

            // 注册操作
            type = "0102";
        }
        Boolean flag = redisTemplate.hasKey("Freeze_" + "Id_"+user.getId() + "_Type_" + 1);
        if(flag){
            log.info("用户账号已经被冻结");
            return ResponseEntity.ok(null);
        }
        // 【生成token并返回】
        String token = JwtUtils.createToken(user.getId(), phone, secret);
        // 问题：没法对token进行统一管理，比如上线剔除、用户更新等
        // 解决：统一管理token，借助redis
        // 实现：把用户信息转换为json存储到redis中，redis中的key就是token
        String userJson = JSON.toJSONString(user);
        // 存储到redis中
        redisTemplate.opsForValue().set(TOKEN_KEY+token,userJson,Duration.ofHours(4));

        // 【记录日志：发送一条MQ消息，交给消费者系统去监听消费消息】
        // a.消息内容
        Map<String,String> map = new HashMap<>();
        map.put("userId",user.getId().toString());
        map.put("type",type);
        map.put("date",new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        // b. 转json
        String logJson = JSON.toJSONString(map);
        try {
            // c. 发送mq消息。 参数1：主题名称（监听消息时候需要对应）
            rocketMQTemplate.convertAndSend("tanhuan-log-151",logJson);
        } catch (MessagingException e) {
            e.printStackTrace();
        }

        //6. 返回
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token",token);
        resultMap.put("isNew",isNew);

        return ResponseEntity.ok(resultMap);
    }

    /**
     * 接口名称：新用户---1填写资料
     * 接口路径：POST/user/loginReginfo
     * 需求描述：保存用户详情。 tb_user_info
     */
    public ResponseEntity<Object> saveUserInfo(UserInfo userInfo, String token) {
        // 根据客户端请求的token进行校验, 并根据token获取用户信息
        User user = findUserByToken(token);
        if (user == null) {
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        // 保存用户详情
        userInfo.setId(user.getId());
        userInfoApi.save(userInfo);
        return ResponseEntity.ok(null);
    }

    // 根据token获取用户信息
    public User findUserByToken(String token) {
        // 因为token存储到redis中，所以可以通过redis获取用户的json字符串
        String key = TOKEN_KEY + token;
        String userJson = redisTemplate.opsForValue().get(key);
        if (userJson == null) {
            return null;
        }
        // string--->User
        User user = JSON.parseObject(userJson, User.class);
        // 更新token时间
        redisTemplate.opsForValue().set(key,userJson,Duration.ofHours(4));
        return user;
    }

    @Autowired
    private AipFaceTemplate aipFaceTemplate;
    @Autowired
    private OssTemplate ossTemplate;
    /**
     * 接口名称：新用户---2选取头像
     */
    public ResponseEntity<Object> updateUserHead(MultipartFile headPhoto, String token) throws IOException {
        //1. 根据token获取用户
        User user = findUserByToken(token);
        if (user == null) {
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        //2. 调用百度云人脸识别
        boolean detect = aipFaceTemplate.detect(headPhoto.getBytes());
        if (!detect) {
            // 人脸识别失败
            return ResponseEntity.status(500).body(ErrorResult.error());
        }

        //3. 头像上传到阿里云oss存储，并获取url
        String url = ossTemplate.upload(headPhoto.getOriginalFilename(), headPhoto.getInputStream());

        //4. 修改头像
        UserInfo userInfo = new UserInfo();
        // 修改条件
        userInfo.setId(user.getId());
        // 修改内容: 头像
        userInfo.setAvatar(url);
        // 修改 (不是全字段更新，只有对象属性不为null时候才会在sql语句中生成更新的字段)
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：用户资料 - 读取
     * @param userID
     * @param huanxinID
     */
    public ResponseEntity<Object> findUserInfById(Long userID, Long huanxinID) {
        System.out.println("--------------");
        System.out.println("--------------");
        System.out.println("--------------");
        System.out.println("--------------");
        System.out.println(StrUtil.format("userId:{},huanxinID:{}",userID,huanxinID));
        //1. 根据token获取用户
        Long userId = UserHolder.getUserId();

        if (userID != null) {
            userId = userID;
        }else if(huanxinID != null){
            userId = huanxinID;
        }


        //2. 根据用户id查询
        UserInfo userInfo = userInfoApi.findById(userId);
        //3. 封装返回结果的vo对象并封装
        UserInfoVo vo = new UserInfoVo();
        // userInfo对象---->拷贝到vo
        // 参数1：数据源（有数据库的对象）； 参数2：目标对象
        BeanUtils.copyProperties(userInfo,vo);
        // 处理age
        if (userInfo.getAge() != null) {
            vo.setAge(userInfo.getAge().toString());
        }
        return ResponseEntity.ok(vo);
    }

    /**
     * 接口名称：用户资料 - 保存
     */
    public ResponseEntity<Object> updateUserInfo(UserInfo userInfo) {
        //1. 根据token获取用户
        User user = UserHolder.get();
        //2. 设置用户id
        userInfo.setId(user.getId());
        //修改用户信息
        userInfoApi.update(userInfo);
        return ResponseEntity.ok(null);
    }


    /**
     * 接口名称：用户通用设置 - 读取
     */
    public ResponseEntity<Object> querySettings() {
        //1. 获取登陆用户
        User user = UserHolder.get();

        //2. 根据用户id，查询陌生人问题（tb_questions）
        Question question = questionApi.findByUserId(user.getId());

        //3. 根据用户id，查询通过设置（tb_settings）
        Settings settings = settingsApi.findByUserId(user.getId());
        if (settings == null) {
            settings = new Settings();
            settings.setLikeNotification(false);
            settings.setGonggaoNotification(false);
            settings.setPinglunNotification(false);
        }

        //4. 返回结果
        SettingsVo vo = new SettingsVo();
        //4.1 设置陌生人问题
        vo.setStrangerQuestion(question != null?question.getTxt():"你喜欢我吗?");
        //4.2 设置手机号
        vo.setPhone(user.getMobile());
        //4.3 封装通用设置
        BeanUtils.copyProperties(settings,vo);

        return ResponseEntity.ok(vo);
    }

    /**
     * 接口名称：通知设置 - 保存
     */
    public ResponseEntity<Object> saveNotifications(Settings param) {
        //1. 获取用户
        User user = UserHolder.get();
        //2. 先根据用户id查询通知设置
        Settings settings = settingsApi.findByUserId(user.getId());
        //3. 判断
        if (settings != null) {
            //3.1 执行修改通知设置
            //不能使用数据拷贝：param中没有id，拷贝到settings后id也为null
            //BeanUtils.copyProperties(param,settings);
            settings.setLikeNotification(param.getLikeNotification());
            settings.setPinglunNotification(param.getPinglunNotification());
            settings.setGonggaoNotification(param.getGonggaoNotification());
            settingsApi.update(settings);
        } else {
            //3.2 执行添加
            settings = new Settings();
            BeanUtils.copyProperties(param,settings);
            // 设置用户id
            settings.setUserId(user.getId());
            settingsApi.save(settings);
        }
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：设置陌生人问题
     * @param content 陌生人问题
     * @return
     */
    public ResponseEntity<Object> saveQuestions(String content) {
        //1. 获取用户
        Long userId = UserHolder.getUserId();
        //2. 先根据用户id查询陌生人问题
        Question question = questionApi.findByUserId(userId);
        //3. 判断
        if (question != null) {
            //3.1 执行修改
            question.setTxt(content);
            questionApi.update(question);
        } else {
            //3.2 执行添加
            question = new Question();
            question.setTxt(content);
            question.setUserId(userId);
            questionApi.save(question);
        }
        return ResponseEntity.ok(null);
    }

    /**
     * 接口名称：黑名单 - 翻页列表
     */
    public ResponseEntity<Object> blacklist(Integer page, Integer pagesize) {
        //1. 获取用户id
        Long userId = UserHolder.getUserId();
        //2. 根据用户id查询黑名单用户
        IPage<UserInfo> iPage = blackListApi.findByPage(userId,page,pagesize);
        //3. 返回PageResult对象
        PageResult pageResult =
                new PageResult(page,pagesize, (int) iPage.getTotal(),iPage.getRecords());
        return ResponseEntity.ok(pageResult);
    }

    /**
     * 接口名称：黑名单 - 移除
     */
    public ResponseEntity<Object> deleteBlackUser(Long blackUserId) {
        blackListApi.delete(UserHolder.getUserId(),blackUserId);
        return ResponseEntity.ok(null);
    }

    @Reference
    private UserLikeApi userLikeApi;
    /**
     * 接口名称：互相喜欢，喜欢，粉丝 - 统计
     * @return
     */
    public ResponseEntity<Object> queryCounts() {
        // 获取用户id
        Long userId = UserHolder.getUserId();
        // 根据用户id查询互相喜欢、喜欢、粉丝
        Long eachLoveCount = userLikeApi.queryEachLoveCount(userId);
        Long loveCount = userLikeApi.queryLoveCount(userId);
        Long fanCount = userLikeApi.queryFanCount(userId);

        // 通过map封装返回结果：eachLoveCount loveCount fanCount
        Map<String,Integer> result = new HashMap<>();
        result.put("eachLoveCount",eachLoveCount.intValue());
        result.put("loveCount",loveCount.intValue());
        result.put("fanCount",fanCount.intValue());
        return ResponseEntity.ok(result);
    }

    /**
     * 接口名称：互相喜欢、喜欢、粉丝、谁看过我 - 翻页列表
     * @param type 类型：
     *   1 互相关注
     *   2 我关注
     *   3 粉丝
     *   4 谁看过我
     * @param page 当前页
     * @param pagesize 页大小
     * @return 返回接口中数据：用户信息、缘分值
     */
    public ResponseEntity<Object> queryUserLikeList(
            Integer type, Integer page, Integer pagesize) {
        // 获取用户id
        Long userId = UserHolder.getUserId();
        PageResult pageResult = null;
        // 判断查询的类型
        switch (type) {
            case 1: //查询互相关注，好友分页列表
                pageResult = userLikeApi.queryEachLoveList(userId,page,pagesize);
                break;
            case 2://查询我关注分页列表
                pageResult = userLikeApi.queryLoveList(userId,page,pagesize);
                break;
            case 3://查询粉丝分页列表
                pageResult = userLikeApi.queryFanList(userId,page,pagesize);
                break;
            case 4://查询访客分页列表
                pageResult = userLikeApi.queryVistorsList(userId,page,pagesize);
                break;
        }
        // 统一获取分页数据 （用户id、缘分值）
        List<Map<String,Object>> list = (List<Map<String, Object>>) pageResult.getItems();
        // 创建返回的vo集合
        List<UserLikeVo> voList = new ArrayList<>();
        if (list != null && list.size()>0) {
            for (Map<String, Object> map : list) {
                // 获取返回的用户数据
                Long uid = (Long) map.get("userId");
                Long score = (Long) map.get("score");
                // 创建vo并封装
                UserLikeVo vo = new UserLikeVo();
                vo.setId(uid);
                UserInfo userInfo = userInfoApi.findById(uid);
                if (userInfo != null) {
                    BeanUtils.copyProperties(userInfo,vo);
                }
                // 设置缘分值
                vo.setMatchRate(score.intValue());

                // 添加到集合
                voList.add(vo);
            }
        }
        // 设置封装结果到pageResult
        pageResult.setItems(voList);
        return ResponseEntity.ok(pageResult);
    }

    @Reference
    private FriendApi friendApi;

    /**
     * 接口名称：粉丝 - 喜欢
     */
    public ResponseEntity<Object> fansLike(Long likeUserId) {
        //* 1、删除粉丝中的喜欢数据 db.user_like.remove({likeUserId:1,userId:23})
        userLikeApi.delete(UserHolder.getUserId(),likeUserId);
        //* 2、记录双向的好友关系
        friendApi.save(UserHolder.getUserId(),likeUserId);
        //* 3、注册好友关系到环信 （喜欢的用户、登陆的用户要先在环信注册）
        huanXinTemplate.contactUsers(UserHolder.getUserId(),likeUserId);
        return ResponseEntity.ok(null);
    }
    public ResponseEntity<Object> sendVerificationCode() {
        User user = UserHolder.get();
        String code="123456";
        smsTemplate.sendSms(user.getMobile(),code);
        redisTemplate.opsForValue().set(SMS_KEY+user.getMobile(),code, Duration.ofMinutes(30));

        return ResponseEntity.ok(null);
    }

    public ResponseEntity<Object> checkVerificationCode(String verificationCode) {
        User user = UserHolder.get();
        String redisCode = redisTemplate.opsForValue().get(SMS_KEY + user.getMobile());

        if(com.aliyuncs.utils.StringUtils.isEmpty(redisCode)||!redisCode.equals(verificationCode)){
            return ResponseEntity.status(500).body(ErrorResult.error());
        }
        HashMap<String, Boolean> map = new HashMap<>();
        map.put("verification",true);
        return ResponseEntity.ok(map);

    }

    public ResponseEntity<Object> upadatePhone(String phone) {
        User user = UserHolder.get();
        //原本的token应该删掉redisTemplate.delete(TOKEN_KEY+)
        //redisTemplate.delete(SMS_KEY+user.getMobile());
        User byMobileUser = userApi.findByMobile(phone);
        if(byMobileUser!=null){
            return ResponseEntity.status(500).body(ErrorResult.mobileError());
        }
        user.setMobile(phone);
        userApi.update(user);
       /* String token = JwtUtils.createToken(user.getId(), user.getMobile(), secret);
        String jsonUserStr = JSON.toJSONString(user);
        redisTemplate.opsForValue().set(TOKEN_KEY+token,jsonUserStr,Duration.ofMinutes(30));
        System.out.println("修改后的手机token为"+TOKEN_KEY+token);*/
        return ResponseEntity.ok(null);
    }
}
